﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using NFit.Core;
using DocumentFormat.OpenXml.Wordprocessing;

namespace NFit.WordML
{
    public class WordDocumentConverter
    {
        private ILogger _logger;
        private Stream _stream;
        private string _fileName;
        private WordFileMap _map;

        public WordDocumentConverter(Stream stream, WordFileMap map, ILogger logger)
        {
            _stream = stream;
            _map = map;
            _logger = logger;

        }

        public WordDocumentConverter(string filename, WordFileMap map, ILogger logger)
        {
            _fileName = filename;
            _map = map;
            _logger = logger;
        }

        public SpecificationDefinition GetSpecifications()
        {
            WordDocumentParser parser = null;
            if (_stream != null)
                parser = new WordDocumentParser(_stream, _map.Properties.Hierarchy, new ConsoleLogger());
            else if (!string.IsNullOrEmpty(_fileName) && File.Exists(_fileName))
                parser = new WordDocumentParser(_fileName, _map.Properties.Hierarchy, new ConsoleLogger());

            if (parser == null)
                throw new ApplicationException("Word document read error, no parser initialized");

            SpecificationDefinition root = new SpecificationDefinition();
            var elementRoot = parser.Parse();
            ReadElement(root, elementRoot, elementRoot);

            return root;
        }

        private void ReadElement(SpecificationDefinition parentSpec, WordElementContainer parentElt, WordElementContainer elt)
        {
            var rootspec = parentSpec;

            if (elt.IsParagraph)
            {
                Paragraph para = elt.Element as Paragraph;
                string paraStyle = para.StyleId();
                if (paraStyle == _map.Properties.SpecStyle && !string.IsNullOrEmpty(_map.Properties.SpecStyle))
                {
                    var spec = ReadSpec(parentSpec, parentElt, elt);
                    parentSpec.AddChildSpec(spec);
                    //rootspec = spec;
                }
                else if (paraStyle == _map.Properties.SetupStyle && !string.IsNullOrEmpty(_map.Properties.SetupStyle))
                {
                    var spec = ReadSpec(parentSpec, parentElt, elt);
                    parentSpec.Setup = spec;
                }
            }
            foreach(var child in elt.Childs)
            {
                ReadElement(rootspec, elt, child);
            }
        }

        private SpecificationDefinition ReadSpec(SpecificationDefinition parentSpec, WordElementContainer parentElt, WordElementContainer elt)
        {
            bool doReadElements = false;
            
            SpecificationDefinition spec = new SpecificationDefinition();
            
            foreach (var child in parentElt.Childs)
            {
                if (child == elt)
                {
                    doReadElements = true;
                    //continue;
                }

                if (doReadElements)
                {
                    _logger.Log("!!!!!!!!!!!!!!! spec elt " + child.Element.GetType().Name + " " + child.Element.InnerText); 
                    if (child.Element is Table)
                    {
                        Table tbl = child.Element as Table;
                        
                        if (tbl.IsInStyle(_map.Properties.TableFixtureStyle))
                        {
                            ReadTableFixture(spec, tbl); 
                        }
                    }
                }
            }

            return spec;
        }

        private void ReadTableFixture(SpecificationDefinition spec, Table tbl)
        {            
            var fixture = spec.AddFixture();
            foreach (var tblrow in tbl.Descendants<TableRow>())
            {
                FixtureRow row = new FixtureRow();
                fixture.Add(row);
                foreach (var cell in tblrow.Descendants<TableCell>())
                {
                    row.AddCell(cell.InnerText);
                }
            }
            _logger.Log("!!!!!!!!!!!!!!! FIXTURE" + tbl.StyleId() + " rows : " + fixture.Rows.Count);
        }
    }
}
